package com.tongtong.controller;

import com.tt.utils.R;
import lombok.Data;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Collections;
import java.util.Comparator;
import java.util.UUID;

@RestController
@RequestMapping("/upload")
@RequiredArgsConstructor
public class FileUploadController {
    @Value("${upload.filePath}")
    private String filepath;

    /**
     * 断线续传
     *
     * @param fileHash
     * @param chunkIndex
     * @return
     */
    @GetMapping("/check")
    public ResponseEntity<?> checkChunk(
            @RequestParam String fileHash,
            @RequestParam Integer chunkIndex) {

        String chunkPath = getChunkPath(fileHash, chunkIndex);
        boolean exists = Files.exists(Paths.get(chunkPath));

        return ResponseEntity.ok(Collections.singletonMap("exists", exists));
    }

    /**
     * 上传分片
     *
     * @param file
     * @param chunkIndex
     * @param totalChunks
     * @param fileHash
     * @param fileName
     * @return
     * @throws IOException
     */
    @PostMapping("/chunk")
    public R uploadChunk(
            @RequestParam("chunk") MultipartFile file,
            @RequestParam Integer chunkIndex,
            @RequestParam Integer totalChunks,
            @RequestParam String fileHash,
            @RequestParam String fileName) throws IOException {

        // 创建分片目录
        String chunkDir = getChunkDir(fileHash);
        if (!Files.exists(Paths.get(chunkDir))) {
            Files.createDirectories(Paths.get(chunkDir));
        }

        // 保存分片
        String chunkPath = getChunkPath(fileHash, chunkIndex);
        file.transferTo(new File(chunkPath));

        return R.ok();
    }

    /**
     * 合并分片
     *
     * @param request
     * @return
     * @throws IOException
     */
    @PostMapping("/merge")
    public R mergeChunks(@RequestBody MergeChunksRequest request) throws IOException {

        String fileHash = request.getFileHash();
        String fileName = request.getFileName();
        fileName = UUID.randomUUID().toString() + "." + fileName.substring(fileName.lastIndexOf(".") + 1);
        int totalChunks = request.getTotalChunks();

        // 创建最终文件
        String finalDir = filepath;
        if (!Files.exists(Paths.get(finalDir))) {
            Files.createDirectories(Paths.get(finalDir));
        }

        String finalPath = Paths.get(finalDir, fileName).toString();
        try (FileOutputStream fos = new FileOutputStream(finalPath)) {
            for (int i = 0; i < totalChunks; i++) {
                String chunkPath = getChunkPath(fileHash, i);
                Files.copy(Paths.get(chunkPath), fos);
            }
        }

        // 删除临时分片
        deleteChunks(fileHash);

        return R.ok().put("filePath", "upload/" + fileName);
    }

    //  ========== 私有方法 ==========
    private String getChunkDir(String fileHash) {
        return Paths.get(filepath + "chunk", fileHash).toString();
    }

    private String getChunkPath(String fileHash, Integer chunkIndex) {
        return Paths.get(getChunkDir(fileHash), chunkIndex.toString()).toString();
    }

    private void deleteChunks(String fileHash) throws IOException {
        String chunkDir = getChunkDir(fileHash);
        Files.walk(Paths.get(chunkDir))
                .sorted(Comparator.reverseOrder())
                .map(Path::toFile)
                .forEach(File::delete);
    }

    @Data
    public static class MergeChunksRequest {
        private String fileHash;
        private String fileName;
        private Integer totalChunks;
    }
}
